﻿#region [ License information          ]
/* ************************************************************
 *
 * Copyright (c) Bjørn Bouet Smith, 2012
 *
 * This source code is subject to terms and conditions of 
 * Microsoft Public License (Ms-PL).
 * 
 * A copy of the license can be found in the license.txt
 * file at the root of this distribution. If you can not 
 * locate the License, please send an email to bjornsmith@gmail.com
 * 
 * By using this source code in any fashion, you are 
 * agreeing to be bound by the terms of the Microsoft 
 * Public License.
 *
 * You must not remove this notice, or any other, from this
 * software.
 *
 * ************************************************************/
#endregion

using System;
using System.IO;
using System.Text;

namespace Smith.BuildExtensions.ConfigurationTransformation
{
    /// <summary>
    /// Handles reading of the different configuration files
    /// </summary>
    public class ConfigReader : IConfigReader
    {
        private readonly string baseDir;

        private readonly string configTemplate;

        private readonly string buildConfiguration;
        private readonly string projectFile;

        /// <summary>
        /// Initializes a new instance of the <see cref="ConfigReader"/> class.
        /// </summary>
        /// <param name="baseDir">The base dir.</param>
        /// <param name="configTemplate">The config template.</param>
        /// <param name="buildConfiguration">The build configuration.</param>
        /// <param name="projectFile">The project file.</param>
        public ConfigReader(string baseDir, string configTemplate, string buildConfiguration, string projectFile)
        {
            this.baseDir = baseDir;
            this.configTemplate = configTemplate;
            this.buildConfiguration = buildConfiguration;
            this.projectFile = projectFile;
        }

        /// <summary>
        /// Gets the build configuration.
        /// </summary>
        public string BuildConfiguration
        {
            get
            {
                return buildConfiguration;
            }
        }

        /// <summary>
        /// Gets the base config, i.e. the shared configuration.
        /// </summary>
        /// <returns>The ConfigSettings that is shared.</returns>
        /// <exception cref="InvalidOperationException">If the base configuration file was not found.</exception>
        public ConfigSettings GetBaseConfig()
        {
            string baseConfigSettingsFile = Path.Combine(baseDir, "config.base.config");
            if (!File.Exists(baseConfigSettingsFile))
            {
                throw new InvalidOperationException(string.Format("Base Configuration file with filename:{0} does not exist", baseConfigSettingsFile));
            }

            return ConfigSettings.LoadFromFile(baseConfigSettingsFile);
        }

        /// <summary>
        /// Tries the get build configuration configuration, i.e. the configuration that matches the current build target.
        /// </summary>
        /// <param name="configSettings">The config settings.</param>
        /// <returns>true if a build configuration was found, false otherwise</returns>
        public bool TryGetBuildConfigurationConfig(out ConfigSettings configSettings)
        {
            string configFileName = "config." + BuildConfiguration + ".config";
            string configFilePath = Path.Combine(baseDir, configFileName);

            if (!File.Exists(configFilePath))
            {
                configSettings = new ConfigSettings();
                return false;
            }

            configSettings = ConfigSettings.LoadFromFile(configFilePath);
            return true;
        }

        /// <summary>
        /// Tries the get project configuration configuration, i.e. the configuration that matches the current project.
        /// </summary>
        /// <param name="configSettings">The config settings.</param>
        /// <returns>true if a configuration was found, false otherwise</returns>
        public bool TryGetProjectConfigurationConfig(out ConfigSettings configSettings)
        {
            int indexOfLastSlash = projectFile.LastIndexOf(Path.DirectorySeparatorChar);

            int indexOfLastPeriod = projectFile.LastIndexOf(".");

            string projectName = projectFile.Substring(indexOfLastSlash + 1, indexOfLastPeriod - indexOfLastSlash - 1);
            
            string configFileName = "config." + projectName + ".config";
            string configFilePath = Path.Combine(baseDir, configFileName);

            if (!File.Exists(configFilePath))
            {
                configSettings = new ConfigSettings();
                return false;
            }

            configSettings = ConfigSettings.LoadFromFile(configFilePath);
            return true;
        }

        /// <summary>
        /// Gets the configuration template that is being used to do transformation on.
        /// </summary>
        /// <returns>The template as a string.</returns>
        /// <exception cref="InvalidOperationException">If the configuration file was not found.</exception>
        public string GetConfigurationTemplate()
        {
            string baseAppSettingsFile = Path.Combine(baseDir, configTemplate);

            if (!File.Exists(baseAppSettingsFile))
            {
                throw new InvalidOperationException(string.Format("Configuration file with filename:{0} does not exist", baseAppSettingsFile));
            }

            return File.ReadAllText(baseAppSettingsFile, Encoding.UTF8);
        }
    }
}
